package com.irdstudio.tdp.executor.core.plugin.util;

import com.irdstudio.tdp.executor.core.plugin.gencode.vo.PaasDeployInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class POJOUtils {

    private static Logger log = LoggerFactory.getLogger(POJOUtils.class);

    private static String javaFieldName(String dbColName) {

        String[] words = StringUtils.split(dbColName, "_");
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            if (i > 0) {
                buffer.append(StringUtils.capitalize(word.toLowerCase()));
            } else {
                buffer.append(word.toLowerCase());
            }
        }
        return buffer.toString();
    }

    /**
     * 将 java property 的驼峰命名转换成 下划线
     * eg: appDeployId => app_deploy_id
     * @param prop
     * @return
     */
    public static String javaPropToColName(String prop) {
        String regx = "[A-Z]";
        Pattern pattern = Pattern.compile(regx);
        Matcher m = pattern.matcher(prop);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "_" + m.group().toLowerCase());
        }
        m.appendTail(sb);
        return sb.toString();
    }

    public static List<Object[]> getPOJOValues(Object bean) {
        if (bean == null) {
            return new ArrayList<>();
        }
        List<Object[]> vals = new ArrayList<>();

        Class<?> cls = bean.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field f : fields) {
            String dbName = javaPropToColName(f.getName());
            Object val = ReflectionTestUtils.invokeGetterMethod(bean, f.getName());
            if (val == null) {
                continue;
            }
            vals.add(new Object[]{dbName, val});
        }
        return vals;
    }

    /**
     * 生成POJO对象
     * @param rs
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> T generatePOJO(ResultSet rs, Class<T> cls) {
        try {
            ResultSetMetaData metaData = rs.getMetaData();
            T t = (T) cls.newInstance();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                String colName = metaData.getColumnName(i);
                String fieldName = javaFieldName(colName);
                Object obj = rs.getObject(colName);
                Field field = ReflectionUtils.findField(cls, fieldName);
                if (field == null) {
                    // 表结构变更
                    continue;
                }
                obj = convertType(obj, field.getType());
                if (field.getName().startsWith("set")) {
                    fieldName = "set" + StringUtils.capitalize(field.getName());
                }
                try {
                    ReflectionTestUtils.invokeSetterMethod(t, fieldName, obj);
                } catch (Exception e) {
                    log.error("{} {} {} {} {}", cls, fieldName, field.getType(), obj, obj == null ? null : obj.getClass());
                }
            }
            return t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    private static Object convertType(Object obj, Class<?> cls) {
        Object result = obj;
        if (cls == BigDecimal.class && obj != null) {
            result = new BigDecimal(obj.toString());
        } else if (Date.class == cls && obj instanceof String && obj != null) {
            try {
                Date date = DateUtils.parseDate(obj.toString(), "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd");
            } catch (ParseException e) {
                result = obj;
            }
        } else if (obj != null && obj instanceof Date && String.class == cls) {
            // 数据返回Date vo类是String
            Date date = (Date) obj;
            String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss");
            result = dateStr;
        }
        return result;
    }
}

